﻿using System;
using System.Collections.Concurrent;
using Algobox.Toolbox.Collections;
using Algobox.Feeds.Finance.MarketData;
using Algobox.Feeds.Finance.Trading;
using Algobox.Objects.Finance.Assets.Stock;
using Algobox.Structure.Finance.Strategies.PriceMatrix;
using Algobox.Structure.Finance.Strategies.SpikeArb;
using Algobox.Structure.Finance.Strategies.Terrapin;
using Algobox.Structure.Finance.Strategies.SmartStoploss;
using System.Windows.Data;
using Algobox.Structure.Finance.Strategies;
using Algobox.Structure.Finance.Strategies.Moss;
using Algobox.Structure.Finance.Strategies.Dastan;

namespace Algobox.Apps.Finance.Zephyr
{
    /// <summary>
    /// Sterling Trader middleware for feed handles and strategies
    /// </summary>
    public class ZephyrApp
    {
        #region Constructors

        public ZephyrApp(
            ConcurrentDictionary<string, StockSecurity> stocks, 
            IMarketFeedAdaptor marketFeed, 
            ITradingFeedAdaptor tradingFeed, 
            ISpikeArbData spikeArbDataHandler, 
            ITerrapinData terrapinDataHandler,
            IMossData mossDataHandler,
            IDastanData dastanDataHandler)
        {
            _dataSpikeArb = spikeArbDataHandler;
            _dataTerrapin = terrapinDataHandler;
            _dataMoss = mossDataHandler;
            _dataDastan = dastanDataHandler;

            MarketFeed = marketFeed;
            TradingFeed = tradingFeed;

            Stocks = stocks;
            
            SmartStoplossManager = new Algobox.Structure.Finance.Strategies.SmartStoploss.SmartStoplossManagement(marketFeed, tradingFeed);

            // Spike Arb strategy manager
            SpikeArbManager = new SpikeArbManagement(marketFeed, tradingFeed, SmartStoplossManager);
            SpikeArbManager.ViewSettings = ViewSpikeArbSettings;
            SpikeArbManager.ViewExecutions = ViewSpikeArbExecutions;

            // Terrapin strategy manager
            TerrapinManager = new TerrapinManagement(marketFeed, tradingFeed);
            TerrapinManager.Strategies = ViewTerrapinStocks;
            TerrapinManager.ViewUnits = ViewTerrapinUnits;
            TerrapinManager.ViewUnitSummary = ViewTerrapinUnitSummary;

            MossManager = new MossManagement(marketFeed, tradingFeed);
            MossManager.Strategies = ViewMossStocks;
            MossManager.ViewUnits = ViewMossUnits;
            MossManager.ViewUnitSummary = ViewMossUnitSummary;

            // Dastan strategy manager
            DastanManager = new DastanManagement(marketFeed, tradingFeed);
            DastanManager.Strategies = ViewDastanStocks;
            DastanManager.ViewUnits = ViewDastanUnits;
            DastanManager.ViewUnitSummary = ViewDastanUnitSummary;

            // Price matrix viewer
            PriceMatrix = new PriceMatrix(marketFeed);
            PriceMatrix.ViewPrices = ViewPriceMatrix;
        }

        static ZephyrApp()
        {            
            // create views
            ViewSpikeArbSettings = new ConcurrentObservableDictionary<string, SpikeArbStockView>();
            ViewSpikeArbExecutions = new ListCollectionView(new ConcurrentObservableCollection<SpikeArbFill>());
            ViewPriceMatrix = new ConcurrentObservableDictionary<IStock, PriceMatrixView>();
            ViewTerrapinStocks = new ConcurrentObservableDictionary<Guid, TerrapinStock>();
            ViewTerrapinUnits = new ListCollectionView(new ConcurrentObservableCollection<TerrapinUnit>());
            ViewTerrapinUnitSummary = new ConcurrentObservableDictionary<Strategy, StrategyUnitSummary>();
            ViewMossStocks = new ConcurrentObservableDictionary<Guid, MossStock>();
            ViewMossUnits = new ListCollectionView(new ConcurrentObservableCollection<MossUnit>());
            ViewMossUnitSummary = new ConcurrentObservableDictionary<Strategy, StrategyUnitSummary>();

            ViewDastanStocks = new ConcurrentObservableDictionary<Guid, DastanStock>();
            ViewDastanUnits = new ListCollectionView(new ConcurrentObservableCollection<DastanUnit>());
            ViewDastanUnitSummary = new ConcurrentObservableDictionary<Strategy, StrategyUnitSummary>();

            Stocks = new ConcurrentDictionary<string, StockSecurity>();
        }

        #endregion
        //////////
        #region Member Variables
        
        /// <summary>
        /// Logger used by this class
        /// </summary>        
        private readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger();

        ISpikeArbData _dataSpikeArb;
        ITerrapinData _dataTerrapin;
        IMossData _dataMoss;
        IDastanData _dataDastan;

        #endregion
        //////////
        #region Properties
        

        /// <summary>
        /// Contiains references to all stocks avaliable in the system
        /// </summary>
        public static ConcurrentDictionary<string, StockSecurity> Stocks { get; private set; }

        public static ConcurrentObservableDictionary<IStock, PriceMatrixView> ViewPriceMatrix { get; private set; }

        public static ConcurrentObservableDictionary<string, SpikeArbStockView> ViewSpikeArbSettings { get; private set; }
        public static ListCollectionView ViewSpikeArbExecutions { get; private set; }

        public static ConcurrentObservableDictionary<Guid, TerrapinStock> ViewTerrapinStocks { get; private set; }
        public static ConcurrentObservableDictionary<Strategy, StrategyUnitSummary> ViewTerrapinUnitSummary { get; private set; }
        public static ListCollectionView ViewTerrapinUnits { get; private set; }

        public static ConcurrentObservableDictionary<Guid, MossStock> ViewMossStocks { get; private set; }
        public static ConcurrentObservableDictionary<Strategy, StrategyUnitSummary> ViewMossUnitSummary { get; private set; }
        public static ListCollectionView ViewMossUnits { get; private set; }

        public static ConcurrentObservableDictionary<Guid, DastanStock> ViewDastanStocks { get; private set; }
        public static ConcurrentObservableDictionary<Strategy, StrategyUnitSummary> ViewDastanUnitSummary { get; private set; }
        public static ListCollectionView ViewDastanUnits { get; private set; }

        /// <summary>
        /// True when strategies have been loaded
        /// </summary>
        public bool IsLoaded { get; private set; }

        /// <summary>
        /// True when strategies have been told to start
        /// </summary>
        public bool IsStarted { get; private set; }
                
        /// <summary>
        /// Maintains SterlingTrader price feed and handles all quote subscriptions
        /// </summary>
        public IMarketFeedAdaptor MarketFeed { get; private set; }

        /// <summary>
        /// Maintains SterlingTrader price feed and handles all quote subscriptions
        /// </summary>
        public ITradingFeedAdaptor TradingFeed { get; private set; }
        
        /// <summary>
        /// The SpikeArb strategy manager
        /// </summary>
        public SpikeArbManagement SpikeArbManager { get; private set; }

        public TerrapinManagement TerrapinManager { get; private set; }

        public MossManagement MossManager { get; private set; }

        public DastanManagement DastanManager { get; private set; }

        public SmartStoplossManagement SmartStoplossManager { get; private set; }

        public PriceMatrix PriceMatrix { get; private set; }
        

        #endregion
        //////////
        #region Functions

        public bool SpikeArbLoad()
        {
            if (_dataSpikeArb.TryLoadStrategySpikeArb(SpikeArbManager))
            {
                Log.Debug("Successfully loaded SpikeArbManager settings from " + _dataSpikeArb.FeedName + ", starting SpikeArb");
                return true;
            }
            else
            {
                Log.Error("Failed to load settings from " + _dataSpikeArb.FeedName);
                return false;
            }
        }

        public void SpikeArbUnload()
        {
            Log.Debug("Unloading SpikeArbManager");
            SpikeArbManager.StopStrategy();
            SpikeArbManager.RemoveAll();    
        }

        public bool SpikeArbSave()
        {
            if (_dataSpikeArb.TrySaveStrategySpikeArb(SpikeArbManager))
            {
                Log.Debug("Successfully saved SpikeArb settings to " + _dataSpikeArb.FeedName);
                return true;
            }
            else
            {
                Log.Error("Failed to save SpikeArb settings to " + _dataSpikeArb.FeedName);
                return false;
            }
        }


        public bool TerrapinLoad()
        {
            if (_dataTerrapin.TryLoadStrategyTerrapin(TerrapinManager))
            {
                Log.Debug("Successfully loaded Terrapin settings from " + _dataTerrapin.FeedName);
                return true;
            }
            else
            {
                Log.Error("Failed to load Terrapin settings from " + _dataTerrapin.FeedName);
                return false;
            }
        }

        public void TerrapinUnload()
        {
            Log.Debug("Unloading Terrapin");
            TerrapinManager.RemoveAll();
        }

        public bool TerrapinSave()
        {
            if (_dataTerrapin.TrySaveStrategyTerrapin(TerrapinManager))
            {
                Log.Debug("Successfully saved Terrapin settings to " + _dataTerrapin.FeedName);
                return true;
            }
            else
            {
                Log.Error("Failed to save Terrapin settings to " + _dataTerrapin.FeedName);
                return false;
            }
        }




        public bool DastanLoad()
        {
            if (_dataDastan.TryLoadStrategyDastan(DastanManager))
            {
                Log.Debug("Successfully loaded Dastan settings from " + _dataDastan.FeedName);
                return true;
            }
            else
            {
                Log.Error("Failed to load Dastan settings from " + _dataDastan.FeedName);
                return false;
            }
        }

        public void DastanUnload()
        {
            Log.Debug("Unloading Dastan");
            DastanManager.RemoveAll();
        }

        public bool DastanSave()
        {
            if (_dataDastan.TrySaveStrategyDastan(DastanManager))
            {
                Log.Debug("Successfully saved Dastan settings to " + _dataDastan.FeedName);
                return true;
            }
            else
            {
                Log.Error("Failed to save Dastan settings to " + _dataDastan.FeedName);
                return false;
            }
        }



        public bool MossLoad(string username)
        {
            if (_dataMoss.TryLoadStrategyMoss(username, MossManager))
            {
                Log.Debug("Successfully loaded Moss settings from " + _dataMoss.FeedName);
                return true;
            }
            else
            {
                Log.Error("Failed to load Moss settings from " + _dataMoss.FeedName);
                return false;
            }
        }

        public void MossUnload()
        {
            Log.Debug("Unloading Moss");
            MossManager.RemoveAll();
        }

        public bool MossSave(string username)
        {
            if (_dataMoss.TrySaveStrategyMoss(username, MossManager))
            {
                Log.Debug("Successfully saved Moss settings to " + _dataMoss.FeedName);
                return true;
            }
            else
            {
                Log.Error("Failed to save Moss settings to " + _dataMoss.FeedName);
                return false;
            }
        }


        public void StartStrategy()
        {
            Log.Info("Starting strategies");

            IsStarted = false; 
            throw new NotImplementedException();            
        }

        /// <summary>
        /// Stops all running strategies, pulls all orders, cancels all quote requests and logs out of SterlingTrader
        /// </summary>
        public void StopStrategy()
        {
            Log.Info("Stopping strategies");

            IsStarted = false;            
        }
        

        #endregion
        //////////
        #region Enums





        #endregion

    }
}
